package com.itheima.concurrent;

import java.util.concurrent.Semaphore;

/**
 * Semaphore用于限制可以访问某些资源（物理或逻辑的）的线程数目，他维护了一个许可证集合，
 * 有多少资源需要限制就维护多少许可证集合，假如这里有N个资源，那就对应于N个许可证，同一时刻也只能有N个线程访问。
 * 一个线程获取许可证就调用acquire方法，用完了释放资源就调用release方法。
 */
public class SemaphoreTest {
    static Semaphore semaphore = new Semaphore(3);
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Student("学生" + i, semaphore).start();
        }
    }

}

class Student extends Thread{
    private String name;
    private Semaphore semaphore;
    public Student(String name,Semaphore semaphore){
        this.name = name;
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        try {
            semaphore.acquire();
            System.out.println(name + "拿到了打饭的许可");
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            System.out.println(name + "打好了饭,释放这个窗口");
            semaphore.release();
        }
    }

    /**
     * 交替打印 A、 B、 C
     */
    public static void main(String[] args) throws Exception {
        Semaphore s1 = new Semaphore(1);
        Semaphore s2 = new Semaphore(1);
        Semaphore s3 = new Semaphore(1);

        s1.acquire();
        s2.acquire();

        new Thread(() -> {
            while (true) {
                try {
                    s1.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("A");
                s2.release();
            }
        }).start();

        new Thread(() -> {
            while (true){
                try {
                    s2.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("B");
                s3.release();
            }
        }).start();

        new Thread(() -> {
            while (true) {

                try {
                    s3.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("C");
                s1.release();
            }
        }).start();
    }
}